package com.ms.service.module.analysis.db;

import java.math.BigDecimal;
import java.util.ArrayList;

import org.hibernate.Query;
import org.hibernate.Session;

import com.ms.game.db.util.UpdateQueryBuilder;
import com.ms.game.slot.base.GainRateData;
import com.ms.game.slot.base.GainRateSystem;
import com.ms.service.module.analysis.GameNameWithHallType;
import com.ms.service.module.analysis.MemberType;
import com.ms.service.module.analysis.PlatformType;
import com.ms.service.module.analysis.async.UpdateRealTimeAnalysisModelAsync;
import com.ms.service.module.analysis.db.model.ClientReportModel;
import com.ms.service.module.analysis.db.model.RealTimeAnalysisModel;
import com.ms.service.module.analysis.db.model.RealTimeAnalysisModelV2;
import com.xpec.c4.db.hibernate.manager.HibernateAnalysisManager;
import com.xpec.c4.game.common.Helper;


public class AnalysisDAO {
	private static class AnalysisDAOInstance{
		public static AnalysisDAO instance = new AnalysisDAO();
	}
	
	public static AnalysisDAO getInstance (){
		return AnalysisDAOInstance.instance;
	}
	
	
	/*
	 * 即時玩家人數與總投注紀錄TABLE名稱
	 */
	public static final String KEY_REAL_TIME_ANALYSIS = "real_time_analysis";
		
	/**
	 * 檢查即時人數與總投注TABLE裡面有沒有紀錄
	 * @param name
	 * @return
	 */
	public boolean CheckRecordInTable(PlatformType platform, GameNameWithHallType name){
		ArrayList<RealTimeAnalysisModel> realTimeAnalysisModels = new ArrayList<RealTimeAnalysisModel>();
		Session session = HibernateAnalysisManager.getSession();
		Query query = session.createQuery("from RealTimeAnalysisModel where platformType = :P and gameNameWithHallType = :G");
		query.setParameter("P", platform);
		query.setParameter("G", name);
		realTimeAnalysisModels = (ArrayList<RealTimeAnalysisModel>) query.list();
		HibernateAnalysisManager.endSession();
		
		//如果DB裡面沒有
		if (realTimeAnalysisModels.size() == 0) return false;
		//如果DB裡面已經有了
		else return true;
	}
	
	/**
	 * 在初始化時新增記錄
	 */
	public void InsertNewRecord(RealTimeAnalysisModel model){	
		Session session = HibernateAnalysisManager.txBegin();
		session.save(model);
		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
	/**
	 * 在初始化時將DB歸零 
	 */
	public void initRealTimeAnalysis(PlatformType platformType, GameNameWithHallType gameNameWithHallType){
		Session session = HibernateAnalysisManager.txBegin();

		UpdateQueryBuilder builder = new UpdateQueryBuilder();
		builder.setSession(session);
		builder.setTableName("RealTimeAnalysisModel");
		
		builder.addSetValue("realTimeMemberFormal", 0);
		builder.addSetValue("realTimeMemberOfflineSpin", 0);
		builder.addSetValue("realTimeMemberTrial", 0);
		builder.addSetValue("realTimeMemberNoAccount", 0);
		
		builder.addSetValue("totalBetFormal", BigDecimal.ZERO);
		builder.addSetValue("totalBetOfflineSpin", BigDecimal.ZERO);
		builder.addSetValue("totalBetTrail", BigDecimal.ZERO);
		builder.addSetValue("totalBetNoAccount", BigDecimal.ZERO);
		
		builder.addSetValue("realTimeBetFormal", BigDecimal.ZERO);
		builder.addSetValue("realTimeBetOfflineSpin", BigDecimal.ZERO);
		builder.addSetValue("realTimeBetTrial", BigDecimal.ZERO);
		builder.addSetValue("realTimeBetNoAccount", BigDecimal.ZERO);
		
		builder.addWhereKey("platformType", platformType);
		builder.addWhereKey("gameNameWithHallType", gameNameWithHallType);
		builder.executeQuery();

		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
	/*
	 * 更新即時在線人數紀錄
	 */
	public void updateRealTimeMember(RealTimeAnalysisModel model, MemberType memberType){
						
		Session session = HibernateAnalysisManager.txBegin();

		UpdateQueryBuilder builder = new UpdateQueryBuilder();
		builder.setSession(session);
		builder.setTableName("RealTimeAnalysisModel");
		
		//選擇要更新的會員類型
		switch (memberType) {
		case FORMAL_MEMBER:{
			builder.addSetValue("realTimeMemberFormal", model.getRealTimeMemberFormal());
			break;
		}
		case OFFLINE_SPIN_MEMBER:{
			builder.addSetValue("realTimeMemberOfflineSpin", model.getRealTimeMemberOfflineSpin());
			break;
		}
		case TRAIL_MEMBER:{
			builder.addSetValue("realTimeMemberTrial", model.getRealTimeMemberTrial());
			break;
		}
		case NO_ACCOUNT:{
			builder.addSetValue("realTimeMemberNoAccount", model.getRealTimeMemberNoAccount());
			break;
		}
		default:
			break;
		}
		
		builder.addWhereKey("platformType", model.getPlatformType());
		builder.addWhereKey("gameNameWithHallType", model.getGameNameWithHallType());
		builder.executeQuery();

		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
	/*
	 * 更新即時在線投注紀錄
	 */
	public void updateRealTimeBet(RealTimeAnalysisModel model, MemberType memberType, boolean isRealTimeBet){
						
		Session session = HibernateAnalysisManager.txBegin();

		UpdateQueryBuilder builder = new UpdateQueryBuilder();
		builder.setSession(session);
		builder.setTableName("RealTimeAnalysisModel");
		
		//選擇要更新的會員類型
		switch (memberType) {
		case FORMAL_MEMBER:{
			if(isRealTimeBet)
				builder.addSetValue("realTimeBetFormal", model.getRealTimeBetFormal());
			else
				builder.addSetValue("totalBetFormal", model.getTotalBetFormal());
			break;
		}	
		case OFFLINE_SPIN_MEMBER:{
			if(isRealTimeBet)
				builder.addSetValue("realTimeBetOfflineSpin", model.getRealTimeBetOfflineSpin());
			else
				builder.addSetValue("totalBetOfflineSpin", model.getTotalBetOfflineSpin());
			break;
		}
		case TRAIL_MEMBER:{
			if(isRealTimeBet)
				builder.addSetValue("realTimeBetTrial", model.getRealTimeBetTrial());
			else
				builder.addSetValue("totalBetTrail", model.getTotalBetTrail());
			break;
		}
		case NO_ACCOUNT:{
			if(isRealTimeBet)
				builder.addSetValue("realTimeBetNoAccount", model.getRealTimeBetNoAccount());
			else
				builder.addSetValue("totalBetNoAccount", model.getTotalBetNoAccount());
			break;
		}
		default:
			break;
		}
				
		builder.addWhereKey("platformType", model.getPlatformType());
		builder.addWhereKey("gameNameWithHallType", model.getGameNameWithHallType());
		builder.executeQuery();

		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
	/**
	 * 新增客戶端回報紀錄
	 * @param model
	 */
	public void insertNewClientReport(ClientReportModel model){
		Session session = HibernateAnalysisManager.txBegin();
		session.save(model);
		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
	
	
	/**
	 * 取得所有Model
	 */
	public static ArrayList<RealTimeAnalysisModelV2> getRealTimeModels(boolean isInit){
		Session session = HibernateAnalysisManager.getSession();
		Query query = session.createQuery("from RealTimeAnalysisModelV2");
		@SuppressWarnings("unchecked")
		ArrayList<RealTimeAnalysisModelV2> models = (ArrayList<RealTimeAnalysisModelV2>) query.list();
		HibernateAnalysisManager.endSession();

		if(isInit){
			ArrayList<RealTimeAnalysisModelV2> newModels = insertNewModelsByExsist(models);
			
			if(newModels.size() > 0){
				models.addAll(newModels);	
			}
		}
		
		return models;
	}
	
	private static ArrayList<RealTimeAnalysisModelV2> insertNewModelsByExsist(ArrayList<RealTimeAnalysisModelV2> exsistModels){
		ArrayList<RealTimeAnalysisModelV2> newModels = new ArrayList<RealTimeAnalysisModelV2>();
		for(PlatformType platformType : PlatformType.values()){
			for(GameNameWithHallType gameHall : GameNameWithHallType.values()){
				String[] gameHallStrs = gameHall.name().split("_");
				String gameType = gameHallStrs[0];
				String hallType = (gameHallStrs.length >= 2) ? gameHallStrs[1] : null;
				
				ArrayList<GainRateData> gainRateDatas = GainRateSystem.getGainRateList(gameType, hallType);
				if(GainRateSystem.isAffectGame(gameType) && gainRateDatas != null){
					
					for(GainRateData gainRateData : gainRateDatas){
						BigDecimal gainRate = gainRateData.getGainRate();
						
						boolean isFoundModel = false;
						for(RealTimeAnalysisModelV2 model : exsistModels){
							if(
									model.getPlatformType().equals(platformType) &&
									model.getGameNameWithHallType().equals(gameHall) &&
									Helper.isEqual(model.getGainRate(), gainRate)
							)
							{
								isFoundModel = true;
								break;
							}
							
						}
						
						if(!isFoundModel){
							RealTimeAnalysisModelV2 model = new RealTimeAnalysisModelV2();
							model.setPlatformType(platformType);
							model.setGameNameWithHallType(gameHall);
							model.setGainRate(gainRate);
							
							newModels.add(model);
						}
					}
					
				}
				else{
					
					boolean isFoundModel = false;
					BigDecimal gainRate = BigDecimal.ONE;
					for(RealTimeAnalysisModelV2 model : exsistModels){
						if(
								model.getPlatformType().equals(platformType) &&
								model.getGameNameWithHallType().equals(gameHall) &&
								Helper.isEqual(model.getGainRate(), gainRate)
						)
						{
							isFoundModel = true;
							break;
						}
					}
					
					if(!isFoundModel){
						RealTimeAnalysisModelV2 model = new RealTimeAnalysisModelV2();
						model.setPlatformType(platformType);
						model.setGameNameWithHallType(gameHall);
						model.setGainRate(gainRate);
						
						newModels.add(model);
					}
					
				}
			}
		}
		
		//有新的model
		if(newModels.size() > 0){
			Session session = HibernateAnalysisManager.txBegin();
			for(RealTimeAnalysisModelV2 model : newModels){
				session.save(model);
			}
			HibernateAnalysisManager.txCommitFailRollbackClearSession();
		}
		
		return newModels;
	}
	
	/**
	 * 更新models
	 */
	public static void updateRealTimeModels(int updateType, ArrayList<RealTimeAnalysisModelV2> models){
		if(models == null || models.size() == 0){
			return;
		}
		
		Session session = HibernateAnalysisManager.txBegin();

		if(updateType == UpdateRealTimeAnalysisModelAsync.ALL){
			for(RealTimeAnalysisModelV2 model : models){
				session.update(model);
			}
		}
		else{
			for(RealTimeAnalysisModelV2 model : models){
				
				UpdateQueryBuilder builder = new UpdateQueryBuilder();
				builder.setSession(session);
				builder.setTableName("RealTimeAnalysisModelV2");
				switch (updateType) {
				case UpdateRealTimeAnalysisModelAsync.MEMBER:{
					builder.addSetValue("realTimeMemberFormal", model.getRealTimeMemberFormal());
					builder.addSetValue("realTimeMemberOfflineSpin", model.getRealTimeMemberOfflineSpin());
					builder.addSetValue("realTimeMemberTrial", model.getRealTimeMemberTrial());
					builder.addSetValue("realTimeMemberNoAccount", model.getRealTimeMemberNoAccount());
					
					break;
				}
				case UpdateRealTimeAnalysisModelAsync.TOTAL_BET:{
					builder.addSetValue("totalBetFormal", model.getTotalBetFormal());
					builder.addSetValue("totalBetOfflineSpin", model.getTotalBetOfflineSpin());
					builder.addSetValue("totalBetTrail", model.getTotalBetTrail());
					builder.addSetValue("totalBetNoAccount", model.getTotalBetNoAccount());
					
					break;
				}
				case UpdateRealTimeAnalysisModelAsync.REAL_TIME_BET:{
					builder.addSetValue("realTimeBetFormal", model.getRealTimeBetFormal());
					builder.addSetValue("realTimeBetOfflineSpin", model.getRealTimeBetOfflineSpin());
					builder.addSetValue("realTimeBetTrial", model.getRealTimeBetTrial());
					builder.addSetValue("realTimeBetNoAccount", model.getRealTimeBetNoAccount());
					
					break;
				}

				default:{
					HibernateAnalysisManager.txCommitFailRollbackClearSession();
					return;
				}
				}
				
				builder.addWhereKey("platformType", model.getPlatformType());
				builder.addWhereKey("gameNameWithHallType", model.getGameNameWithHallType());
				builder.addWhereKey("gainRate", model.getGainRate());
				builder.executeQuery();
				
			}
		}
		
		HibernateAnalysisManager.txCommitFailRollbackClearSession();
	}
	
}
